<template>
  <div
    ref="mainRef"
    :class="[
      'DateSelV2',
      hasBorder ? (inputStep == null ? 'unFocus' : 'focus') : '',
      size == 'mini' ? 'miniSize' : size == 'tiny' ? 'tinySize' : 'normalSize',
      needTimeIcon ? '' : 'pl-0',
      dateShow ? 'min-w-120' : '',
      disabled ? 'disabled' : ''
    ]"
    :tabindex="disabled ? null : 1"
    @keyup="handlePress"
    @blur="handleBlur"
    @focus="handleInit(true)"
  >
    <!-- 时间小图标 -->
    <div v-if="needTimeIcon" class="time-icon">
      <i class="el-icon-time"></i>
    </div>
    <span
      v-show="
        dateShow &&
        !(
          displayNum == true &&
          inputStep == null &&
          (value === null || value == '')
        )
      "
      style="flex-shrink: 0"
      :style="dateStyle"
    >
      {{ formatTime(dateValue, 'yyyy-MM-dd') }}
      <!-- 选择日期 -->
      <span
        v-show="datePickerShow && !(displayNum == true && inputStep == null)"
      >
        <i class="el-icon-caret-bottom icon left" @click="handlePickDate"></i>
      </span>
    </span>
    <span
      v-show="
        !(
          displayNum == true &&
          inputStep == null &&
          (value === null || value == '')
        )
      "
      style="flex-shrink: 0"
    >
      <span
        :class="[
          'timeItem',
          size == 'tiny' ? '' : 'ml-3',
          inputStep == 0 ? 'sel' : ''
        ]"
        @click="handleSel(0)"
      >
        {{ valArr[0] }}
      </span>
      <span
        :class="['timeItem', inputStep == 1 ? 'sel' : '']"
        @click="handleSel(1)"
      >
        {{ valArr[1] }}
      </span>
      <span class="left">:</span>
      <span
        :class="['timeItem', inputStep == 2 ? 'sel' : '']"
        @click="handleSel(2)"
      >
        {{ valArr[2] }}
      </span>
      <span
        :class="['timeItem', inputStep == 3 ? 'sel' : '']"
        @click="handleSel(3)"
      >
        {{ valArr[3] }}
      </span>
    </span>

    <!-- 日期选择器 -->
    <el-date-picker
      ref="datePickerRef"
      v-model="dateValue"
      value-format="timestamp"
      class="datePicker"
      type="datetime"
      placeholder="选择日期"
      :format="format"
      :picker-options="pickerOptions"
      @change="handleSub('datePicker')"
    />
    <!-- 清空 -->
    <div v-if="inputStep !== null && !noClear" class="clear">
      <i class="el-icon-circle-close clearIcon left" @click="handleClean"></i>
    </div>
    <!-- disabled -->
    <div v-if="disabled" class="obscuration" />
  </div>
</template>

<script>
import { format, startOfDay } from 'date-fns'
import { cloneDeep } from 'lodash-unified'
import { defineComponent, reactive, toRefs, watch } from 'vue'

import { formatTime } from '@/utils/format'

export default defineComponent({
  name: 'DateSelection',
  props: {
    simpleOp: {
      type: Boolean,
      default: () => false
    },
    disabled: {
      type: Boolean,
      default: () => false
    },
    size: {
      type: String,
      default: () => 'mini'
    },
    noClear: {
      type: Boolean,
      default: () => false
    },
    value: {
      type: [Number, String, Date],
      default: () => null
    },
    displayNum: {
      type: Boolean,
      default: () => false
    },
    pickerOptions: {
      type: Object,
      default: () => {}
    },
    datePickerShow: {
      type: Boolean,
      default: () => true
    },
    hasBorder: {
      type: Boolean,
      default: () => true
    },
    valueFormat: {
      type: String,
      default: () => 'timestamp'
    },
    format: {
      type: String,
      default: 'yyyy-MM-dd HH:mm:ss'
    },
    timeVerify: {
      type: Array,
      default: () => ['00:00', '23:59']
    },
    dateShow: {
      type: Boolean,
      default: () => false
    },
    needTimeIcon: {
      type: Boolean,
      default: () => true
    },
    defaultTime: {
      type: String,
      default: () => null
    },
    dateStyle: {
      type: String,
      default: () => 'padding-right: 5px;'
    }
  },
  emits: ['onchange', 'input'],
  setup(props, { emit }) {
    const state = reactive({
      datePickerRef: {},
      mainRef: {},
      inputStep: null,
      clean: false,
      valArr: [0, 1, 2, 3],
      dateValue: Number(new Date()),
      lastDateValue: null
    })

    /**
     * 初始化
     */
    function handleInit(isStart) {
      let valArr = [],
        date = null
      // 初始化时分参数
      if (props.value == null || props.value == '') {
        if (isStart) {
          date = props.defaultTime
            ? new Date(
                format(new Date(), 'yyyy-MM-dd') + ' ' + props.defaultTime
              )
            : new Date()
        } else {
          date = startOfDay(new Date())
        }
      } else {
        if (
          /^[0-9]*$/.test(props.value) ||
          /\s/.test(props.value) ||
          typeof props.value === 'object'
        ) {
          date = new Date(props.value)
        } else {
          date = new Date(format(new Date(), 'yyyy-MM-dd') + ' ' + props.value)
        }
      }
      const dateStr =
        date.getHours().toString().padStart(2, '0') +
        date.getMinutes().toString().padStart(2, '0')
      valArr = dateStr.split('')
      state.valArr = valArr
      state.dateValue = Number(date)
      if (isStart) {
        state.lastDateValue = Number(date)
        handleSel(0)
      }
    }

    /**
     * 选择
     */
    function handleSel(val) {
      state.inputStep = val
    }

    /**
     * 编辑状态下 输入响应事件
     */
    function handlePress(e) {
      const valArr = cloneDeep(state.valArr)
      // 删除
      if (e.keyCode == 8) {
        state.valArr[state.inputStep] = 0
        if (state.inputStep > 0) {
          state.inputStep--
        }
      }
      // 左移
      else if (e.keyCode == 37 && state.inputStep > 0) {
        state.inputStep--
      }
      // 右移
      else if (e.keyCode == 39 && state.inputStep < 3) {
        state.inputStep++
      }
      // 回车（确认）
      else if (e.keyCode == 13) {
        handleSub()
      }
      // 数字
      else if (isNumber(e.key)) {
        const val = e.key
        valArr[state.inputStep] = val
        state.valArr = valArr
        if (state.inputStep < 3) {
          state.inputStep++
        }
      }
    }

    /**
     * 判断数字
     */
    function isNumber(value) {
      //验证是否为数字
      const patrn = /^(-)?\d+(\.\d+)?$/
      if (patrn.exec(value) == null || value == '') {
        return false
      }
      return true
    }

    /**
     * 开始编辑日期
     */
    function handlePickDate() {
      state.datePickerRef.handleFocus()
      state.inputStep = null
    }

    /**
     * 提交
     */
    function handleSub(type) {
      if (!state.clean) {
        handleVerify()
        const date = new Date(state.dateValue)
        let valStr =
          date.getFullYear() +
          '/' +
          (date.getMonth() + 1 + '').padStart(2, '0') +
          '/' +
          (date.getDate() + '').padStart(2, '0') +
          ' ' +
          (state.valArr[0] || 0) +
          (state.valArr[1] || 0) +
          ':' +
          (state.valArr[2] || 0) +
          (state.valArr[3] || 0) +
          ':00'
        if (type === 'datePicker') {
          valStr = state.dateValue
        }
        let returnVal
        const curTimestamp = Number(new Date(valStr))
        if (props.valueFormat === 'timestamp') {
          returnVal = curTimestamp
        } else {
          returnVal = format(new Date(valStr), props.valueFormat)
        }
        emit('input', returnVal)
        if (state.lastDateValue != curTimestamp) {
          state.lastDateValue = curTimestamp
          emit('onchange', returnVal)
        }
        state.inputStep = null
      } else {
        emit('input', null)
        if (state.lastDateValue != null) {
          state.lastDateValue = null
          emit('onchange', null)
        }
        state.clean = false
      }
    }

    /**
     * 失去焦点
     */
    function handleBlur() {
      if (props.simpleOp) {
        handleSub()
      }
      state.inputStep = null
      handleInit()
    }

    /**
     * 清除数据
     */
    function handleClean() {
      state.valArr = [0, 0, 0, 0]
      state.clean = true
      state.inputStep = null
      emit('onchange', null)
      state.mainRef.blur()
    }

    /**
     * 校验
     */
    function handleVerify() {
      const arr = cloneDeep(state.valArr)
      let timeVerify
      if (props.timeVerify.length == 2) {
        timeVerify = props.timeVerify
      } else {
        timeVerify = ['00:00', '23:59']
      }
      const startHour = timeVerify[0].split(':')[0]
      const startMinute = timeVerify[0].split(':')[1]
      const endHour = timeVerify[1].split(':')[0]
      const endMinute = timeVerify[1].split(':')[1]
      const currentTime =
        Number(arr[0] + arr[1]) * 60 * 60 * 1000 +
        Number(arr[2] + arr[3]) * 60 * 1000
      if (currentTime > endHour * 60 * 60 * 1000 + endMinute * 60 * 1000) {
        arr[0] = endHour.split('')[0]
        arr[1] = endHour.split('')[1]
        arr[2] = endMinute.split('')[0]
        arr[3] = endMinute.split('')[1]
      } else if (
        currentTime <
        startHour * 60 * 60 * 1000 + startMinute * 60 * 1000
      ) {
        arr[0] = startHour.split('')[0]
        arr[1] = startHour.split('')[1]
        arr[2] = startMinute.split('')[0]
        arr[3] = startMinute.split('')[1]
      }
      state.valArr = arr
    }

    // function focus() {
    //   state.mainRef.focus()
    // }

    watch(
      () => props.value,
      () => {
        handleInit()
      },
      { immediate: true }
    )

    return {
      ...toRefs(state),
      formatTime,
      handlePress,
      handleBlur,
      handleInit,
      handleSel,
      handlePickDate,
      handleSub,
      handleClean
    }
  }
})
</script>
<style lang="scss" scoped>
.miniSize {
  // width: 81px;
  min-height: 20px;
  // line-height: 20px;
  font-size: 14px;

  .icon {
    // margin-top: 3px;
  }

  .clearIcon {
    color: #f56c6c;
    // margin-top: 3px;
    margin-left: 5px;
    cursor: pointer;
  }

  .timeItem {
    width: 8px;
    height: 100%;
    text-align: center;
    cursor: pointer;
    float: left;
  }
}

.tinySize {
  // width: 81px;
  min-height: 20px;
  line-height: 20px;
  font-size: 14px;

  .icon {
    // margin-top: 3px;
  }

  .clearIcon {
    color: #f56c6c;
    // margin-top: 3px;
    margin-left: 5px;
    cursor: pointer;
  }

  .timeItem {
    // width: 8px;
    height: 100%;
    text-align: center;
    cursor: pointer;
    float: left;
  }
}

.normalSize {
  // width: 100px;
  min-height: 28px;
  line-height: 28px;
  font-size: 16px;

  .icon {
    // margin-top: 5px;
  }

  .clearIcon {
    color: #f56c6c;
    // margin-top: 5px;
    margin-left: 5px;
    cursor: pointer;
  }

  .timeItem {
    width: 12px;
    height: 100%;
    text-align: center;
    cursor: pointer;
    float: left;
  }
}

.unFocus {
  // border: 1px solid rgba($color: #000000, $alpha: 0);
  border: 1px solid #dcdfe6;
}

.focus {
  border: 1px solid #409eff;
}

.DateSelV2 {
  // display: inline-block;
  width: 220px;
  height: 32px;
  padding: 0 32px;
  display: flex;
  align-items: center;
  border-radius: 4px;
  background-color: #fff;
  user-select: none;
  position: relative;
  font-family: sans-serif;

  // &.disabled {
  //   background-color: #f5f7fa;
  //   border-color: #dfe4ed;
  //   color: #c0c4cc;
  // }

  .time-icon {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .icon {
    cursor: pointer;
  }

  .clear {
    position: absolute;
    right: 0;
    top: 0;
    height: 100%;
    // width: 32px;
    padding-right: 5px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .ml-3 {
    margin-left: 3px;
  }

  .sel {
    background-color: #0171fc;
    color: #fff;
  }

  .datePicker {
    visibility: hidden;
    position: absolute;
    top: 0;
    left: 0;
  }

  .obscuration {
    position: absolute;
    z-index: 100;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
    // cursor: not-allowed;
  }

  .el-icon-caret-bottom {
    position: relative;
    z-index: 1;
  }
}

.pl {
  &-0 {
    padding-left: 0;
  }
}

.min-w {
  &-130 {
    min-width: 130px;
  }

  &-180 {
    min-width: 180px;
  }

  &-120 {
    // min-width: 120px;
  }
}
</style>
